HAL SDIO initialization and configuration functions migration

The goal of this page is to show how to migrate the initialization sequence using STM32CubeMX2:

  • Open STM32CubeMX2 SDMMC configuration panel.

  • Configure the SW layer HAL.

  • Configure the SDIO main features.

  • Configure the advanced SDIO features.

  • Configure the SDIO security and privilege features if needed.

  • Configure the SDIO GPIO pins.

  • Configure the NVIC if the application requires the SDIO to be used in IT mode.

  • Generate the code.

HAL SDIO configuration panel

Create a new project with STM32CubeMX2, start by enabling the SDMMC1 instance as SDIO, as shown in this example with the selected SDMMC1, then start the initialization and the main configuration.

Project configuration panel

HAL SDIO main features configuration

  • The bus width and transfer frequency are selected according to the SDIO device and SDMMC capabilities.

  • The Clock Edge, Clock Power Save, and Hardware Flow Control options can be configured as needed.

  • Users can either choose the default timeout values or set custom ones for data transmission and control operations.

SDIO main feature configuration

HAL SDIO advanced features configuration

  • Advanced feature: The Delay Block can be configured and enabled under the advanced features section. This is recommended for high-speed SDIO operation and is available on supported STM32 series.

  • Enable the Delay Block and choose the appropriate clock phase value to optimize timing and improve data throughput.

SDIO advanced feature configuration

HAL SDIO security and privilege features configuration

Configure the SDIO security and privilege features if needed.

SDIO security and privilege feature configuration

GPIO configuration

Configure the GPIOs required for SDMMC operation. Assign the appropriate pins for SDMMC signals (such as CMD, CLK, and DAT lines) according to your hardware design and SDIO requirements. Set the pin modes, speeds, and alternate functions as specified by the STM32CubeMX2 tool to ensure proper electrical characteristics and reliable communication with the SDIO device.

GPIO Configuration

NVIC configuration

Configure the NVIC in case of an interrupt.

NVIC configuration

Generated SDIO initialization and de-initialization sequences

The SDIO initialization sequence is generated in the mx_sdmmc1_sdio_init function in mx_sdmmc1.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

Related concepts:

STM32CubeMX2 Generated : SDIO initialization and De-initialization sequence

HAL 1 Code Snippet

HAL 2 Code Snippet

Handle declaration

SDIO_HandleTypeDef hsdio1;
static hal_sdio_handle_t hSDMMC1;

Initialization and configuration sequence

static void MX_SDMMC1_SDIO_Init(void)
{

  hsdio1.Instance = SDMMC1;
  hsdio1.Init.ClockEdge = SDMMC_CLOCK_EDGE_FALLING;
  hsdio1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  hsdio1.Init.BusWide = SDMMC_BUS_WIDE_1B;
  hsdio1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  hsdio1.Init.ClockDiv = 0;
  if (HAL_SDIO_Init(&hsdio1) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_SDIO_MspInit(SDIO_HandleTypeDef* hsdio)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(hsdio->Instance==SDMMC1)
  {
  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;
    PeriphClkInit.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* Peripheral clock enable */
    __HAL_RCC_SDMMC1_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SDMMC1 GPIO Configuration
    PC12     ------> SDMMC1_CK
    PC4     ------> SDMMC1_CMD
    PB13     ------> SDMMC1_D0
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF6_SDMMC1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SDMMC1 interrupt Init */
    HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);

  }

}
hal_sdio_handle_t *mx_sdmmc1_sdio_init(void)
{
  hal_sdio_config_t sdio_config;

  if (HAL_SDIO_Init(&hSDMMC1, HAL_SDIO_CARD_1) != HAL_OK)
  {
    return NULL;
  }

  /* SDIO GPIO Configuration **************************************************/

  HAL_RCC_GPIOC_EnableClock();

  HAL_RCC_GPIOB_EnableClock();

    hal_gpio_config_t  gpio_config;

  /**
    SDMMC1 GPIO Configuration

    [GPIO Pin] ------> [Signal Name]

       PC12    ------>   SDMMC1_CK
       PC4     ------>   SDMMC1_CMD
    **/
  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_11;
  HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_12 | HAL_GPIO_PIN_4, &gpio_config);

  /**
    SDMMC1 GPIO Configuration

    [GPIO Pin] ------> [Signal Name]

       PB13    ------>   SDMMC1_D0
    **/
  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_6;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_13, &gpio_config);

    if (HAL_RCC_SDMMC1_SetKernelClkSource(HAL_RCC_SDMMC1_CLK_SRC_PLL1) != HAL_OK)
  {
    return NULL;
  }

  HAL_RCC_SDMMC1_EnableClock();
  sdio_config.clk_cfg.clk_edge       = HAL_SDIO_CLOCK_EDGE_FALLING;
  sdio_config.clk_cfg.clk_power_save = HAL_SDIO_CLOCK_POWER_SAVE_DISABLE;
  sdio_config.bus_wide               = HAL_SDIO_BUS_WIDE_1BIT;
  sdio_config.hw_flow_ctrl           = HAL_SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  sdio_config.clk_cfg.clk_hz         = 400000;
  sdio_config.transceiver            = HAL_SDIO_TRANSCEIVER_NOT_PRESENT;
  sdio_config.data_timeout_cycle     = HAL_SDIO_DATA_MAX_TIMEOUT;
  if (HAL_SDIO_SetConfig(&hSDMMC1, &sdio_config, NULL) != HAL_OK)
  {
    return NULL;
  }
  if (HAL_SDIO_SetFifoThreshold(&hSDMMC1,  HAL_SDIO_FIFO_THRESHOLD_NOT_USED) != HAL_OK)
  {
    return NULL;
  }
  /* Enable the interruption for SDIO */
  HAL_CORTEX_NVIC_SetPriority(SDMMC1_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
  HAL_CORTEX_NVIC_EnableIRQ(SDMMC1_IRQn);
  return &hSDMMC1;
}

Deinitialization sequence

/* User should call the HAL_SD_DeInit() function             */
/* HAL_SD_MspDeInit is called inside HAL_SD_DeInit function */
void HAL_SDIO_MspDeInit(SDIO_HandleTypeDef* hsdio)
{
  if(hsdio->Instance==SDMMC1)
  {
    /* Peripheral clock disable */
    __HAL_RCC_SDMMC1_CLK_DISABLE();

    /**SDMMC1 GPIO Configuration
    PC12     ------> SDMMC1_CK
    PC4     ------> SDMMC1_CMD
    PB13     ------> SDMMC1_D0
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_4);

    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);

    /* SDMMC1 interrupt DeInit */
    HAL_NVIC_DisableIRQ(SDMMC1_IRQn);

  }

}
void mx_sdmmc1_sdio_deinit(void)
{
  /* Disable the interruption for SDIO */
  HAL_CORTEX_NVIC_DisableIRQ(SDMMC1_IRQn);

  (void)HAL_SDIO_DeInit(&hSDMMC1);

  HAL_RCC_SDMMC1_Reset();

  HAL_RCC_SDMMC1_DisableClock();

    /* De-initialize all GPIO pins associated with SDMMC1 */
    HAL_GPIO_DeInit(HAL_GPIOC, HAL_GPIO_PIN_4 | HAL_GPIO_PIN_12);

    HAL_GPIO_DeInit(HAL_GPIOB, HAL_GPIO_PIN_13);

  #if defined(USE_HAL_GPIO_HSLV) && (USE_HAL_GPIO_HSLV == 1U)
    HAL_GPIO_DisableHighSpeedLowVoltage(HAL_GPIOC, HAL_GPIO_PIN_4 | HAL_GPIO_PIN_12);
  #endif /* USE_HAL_GPIO_HSLV */
  #if defined(USE_HAL_GPIO_HSLV) && (USE_HAL_GPIO_HSLV == 1U)
    HAL_GPIO_DisableHighSpeedLowVoltage(HAL_GPIOB, HAL_GPIO_PIN_13);
  #endif /* USE_HAL_GPIO_HSLV */
}

HAL1 / HAL2 Code Snippet

IRQ handle function

void SDMMC1_IRQHandler(void)
{
  HAL_SDIO_IRQHandler(&hSDMMC1);
}